<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Websocket Chat Broker</title>

    <style>
      :root {
        font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
          Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
        font-size: 18px;
      }

      input[type='text'] {
        font-size: inherit;
      }

      #log {
        width: 30em;
        height: 20em;
        overflow: auto;
        margin: 0.5em 0;

        border: 1px solid black;
      }

      #status {
        padding: 0 0.2em;
      }

      #text {
        width: 17em;
        padding: 0.5em;
      }

      .msg {
        margin: 0;
        padding: 0.25em 0.5em;
      }

      .msg--status {
        /* a light yellow */
        background-color: #ffffc9;
      }

      .msg--message {
        /* a light blue */
        background-color: #d2f4ff;
      }

      .msg--error {
        background-color: pink;
      }
    </style>
  </head>
  <body>
    <h1>Chat!</h1>

    <div>
      <button id="connect">Connect</button>
      <span>Status:</span>
      <span id="status">disconnected</span>
    </div>

    <div id="log"></div>

    <form id="chatform">
      <input type="text" id="text" />
      <input type="submit" id="send" />
    </form>

    <hr />

    <section>
      <h2>Commands</h2>
      <table style="border-spacing: 0.5em;">
        <tr>
          <td>
            <code>/list</code>
          </td>
          <td>
            list all available rooms
          </td>
        </tr>
        <tr>
          <td>
            <code>/join name</code>
          </td>
          <td>
            join room, if room does not exist, create new one
          </td>
        </tr>
        <tr>
          <td>
            <code>/name name</code>
          </td>
          <td>
            set session name
          </td>
        </tr>
        <tr>
          <td>
            <code>some message</code>
          </td>
          <td>
            just string, send message to all peers in same room
          </td>
        </tr>
      </table>
    </section>

    <script>
      const $status = document.querySelector('#status')
      const $connectButton = document.querySelector('#connect')
      const $log = document.querySelector('#log')
      const $form = document.querySelector('#chatform')
      const $input = document.querySelector('#text')

      /** @type {WebSocket | null} */
      var socket = null

      function log(msg, type = 'status') {
        $log.innerHTML += `<p class="msg msg--${type}">${msg}</p>`
        $log.scrollTop += 1000
      }

      function connect() {
        disconnect()

        const { location } = window

        const proto = location.protocol.startsWith('https') ? 'wss' : 'ws'
        const wsUri = `${proto}://${location.host}/ws`

        log('Connecting...')
        socket = new WebSocket(wsUri)

        socket.onopen = () => {
          log('Connected')
          updateConnectionStatus()
        }

        socket.onmessage = (ev) => {
          log('Received: ' + ev.data, 'message')
        }

        socket.onclose = () => {
          log('Disconnected')
          socket = null
          updateConnectionStatus()
        }
      }

      function disconnect() {
        if (socket) {
          log('Disconnecting...')
          socket.close()
          socket = null

          updateConnectionStatus()
        }
      }

      function updateConnectionStatus() {
        if (socket) {
          $status.style.backgroundColor = 'transparent'
          $status.style.color = 'green'
          $status.textContent = `connected`
          $connectButton.innerHTML = 'Disconnect'
          $input.focus()
        } else {
          $status.style.backgroundColor = 'red'
          $status.style.color = 'white'
          $status.textContent = 'disconnected'
          $connectButton.textContent = 'Connect'
        }
      }

      $connectButton.addEventListener('click', () => {
        if (socket) {
          disconnect()
        } else {
          connect()
        }

        updateConnectionStatus()
      })

      $form.addEventListener('submit', (ev) => {
        ev.preventDefault()

        const text = $input.value

        log('Sending: ' + text)
        socket.send(text)

        $input.value = ''
        $input.focus()
      })

      updateConnectionStatus()
    </script>
  </body>
</html>
